home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir30
/
alsps.zip
/
ALSP5.DOC
< prev
next >
Wrap
Lisp/Scheme
|
1993-11-04
|
14KB
|
427 lines
This is Lesson 5 of a series of AutoLISP training exercises given
on the CompuServe ADESK Forum by the Autodesk, Inc. Training
Department.
WRITING NEW AUTOCAD COMMANDS
SUBRS ARE ATOMS
AutoLISP has two kinds of objects: atoms and lists. Every object
in AutoLISP is one or the other. The empty list nil () is by
definition both an atom and a list, and the only object in
AutoLISP that can be both.
Atoms come in many different data types. One of these data types
is the SUBR, or sub-routine. Subrs are names for AutoLISP
internal functions. All of the AutoLISP subrs are listed in
chapters 4 and 5 of the AutoLISP Programmer's Reference (APR).
FUNCTIONS ARE FIRST IN FORMS
When a complex expression is constructed with the intent of being
evaluated, it consists of a list with a subr (or internal
function) as its first element. Such an expression is also known
as a form.
This is an example of a form.
(setq x 10)
What is the subr in this example? What position does it occupy
in the list?
This is an example of a list that is not a form, that is, a list
that must be treated only as data and cannot be evaluated.
(1.0 2.0 3.0)
What would happen if AutoLISP attempted to evaluate the latter
expression? Why?
This leads us to the important distinction that any list that can
be evaluated (any form) must have a function as its first
element.
USER DEFINED FUNCTIONS
In addition to its many subrs, AutoLISP allows the creation of
user-defined functions, that is, functions whose instruction sets
and names have been defined by the user.
Consider the evaluation process of a typical form that uses a
subr.
(setq x 10)
AutoLISP evaluates the first element, where it expects to find a
function. Here, it finds the subr SETQ, and retrieves the
binding of SETQ. The binding of SETQ (in fact, the binding of
any subr) is effectively a set of instructions on how processing
should proceed. Next, AutoLISP evaluates the arguments to SETQ
in order, and finally applies the binding of SETQ (processing
instructions) to the values of the arguments.
The result in this case is a value of 10 for the expression, and
a side-effect of variable X being bound to 10.
SETQ is a subr, and its instructions have been pre-defined in
AutoLISP; the user cannot change them. However, it's possible to
create entirely new functions that perform whatever processing
instructions the user desires.
New function bindings are created through use of the subr DEFUN,
which stands for DEfine FUNction.
HOW TO USE DEFUN
The syntax of DEFUN appears slightly different than that of other
functions you've used in this tutorial, but it's really the same.
(defun <sym name> <arg list / local var> <expr> ...)
DEFUN takes two required arguments, and a variable number of
arguments following the first two.
ARGUMENTS TO DEFUN
The first required argument to DEFUN must be the symbol name of
the new function to be defined. Never use the name of a built-in
function or symbol as <sym name>, since this will make the
built-in function inaccessible. Use a new name that you have
created, preferably one that describes the actions of the
function. Using function names of six or fewer characters will
save memory space (more about that in future lessons).
In this example, the first argument to DEFUN is the symbol name
MYFUN, which becomes the name of the user-defined function.
(defun MYFUN <arg list / local var> ... )
The second required argument to DEFUN must be a list of required
arguments and/or local variables. This argument will be
discussed in detail later in this lesson. For now, it is
sufficient to use an empty list, that is, a list with no required
arguments or local variables.
The previous example is expanded to include the list of required
arguments and/or local variables.
(defun MYFUN () <expr> ... )
Arguments following the list of required arguments are
expressions to be evaluated when the user-defined function is
executed. They are the processing instructions that will be
executed when the function is called.
EXAMPLE OF SIMPLE FUNCTION DEFINITION
In the next few examples, optional expressions will be added to
the body of MYFUN. Different sets of expressions will give
different meaning to MYFUN.
In this example, MYFUN's instructions tell it to ask the user for
two points, and to print the distance between the two points.
The AutoLISP subr DISTANCE is introduced. DISTANCE takes two
points as arguments, and calculates the 3D distance between the
points.
(defun MYFUN ()
(setq pt1 (getpoint "\nFrom point: "))
(setq pt2 (getpoint pt1 "\nTo point: "))
(distance pt1 pt2)
)
Type in the example. AutoLISP will return the name of the
function that's been defined; in this case, MYFUN. Call MYFUN as
you would any subr.
Command: (MYFUN)
From point: <pick>
To point: <pick>
<returns distance as a real number>
VALUES RETURNED BY USER DEFINED FUNCTIONS
Any function created by DEFUN will return a value when it is
called, just as any subr returns a value. The value returned by
a user-defined function will be the value of the last expression
in the body of expressions that comprise the processing
instructions.
For example, in the previous example the value of the expression
(myfun) will be the value of the expression (distance pt1 pt2).
(myfun) <----- form calling user-defined function
(defun MYFUN ()
(setq pt1 (getpoint "\nFrom point: "))
(setq pt2 (getpoint pt1 "\nTo point: "))
(distance pt1 pt2) <----- value of last expression
) becomes value of form
SAVING FUNCTION DEFINITIONS TO DISK
Although it's possible to create user-defined functions by typing
in the appropriate code at the command prompt, it's probably a
better idea to use a text editor of your choice (EDLIN will
always do in a pinch) and add this text to a new file with an
extension of .LSP; you choose the name. Then, load the file into
the drawing editor with the AutoLISP LOAD function.
The LOAD function takes a single string argument, which should be
the name of the .LSP file to load.
(load "<filename>")
Remember that the AutoCAD Load command is quite a different thing
from the AutoLISP LOAD function.
For example, if you add the code from the previous example to a
file named MYFUN.LSP then you can load the file into the drawing
editor as follows.
Use a text editor to create a text file named MYFUN.LSP and
include the code that creates this user-defined function. Then
load the file in to the AutoCAD drawing editor.
Command: (load "MYFUN")
MYFUN
AutoLISP will search the current directory, along with the other
directories in the AutoCAD Library Path, for the file MYFUN.LSP.
If it finds the file, it will load the code into the editor.
If AutoLISP generates an error message when loading the file, you
should edit the file and fix the problem.
For a description of the directories in the AutoCAD Library Path,
see section 4.45, "(findfile <filename>)", of the APR.
CALLING AUTOCAD COMMANDS FROM AUTOLISP
A very popular application for user-defined functions is to
create abbreviated names for AutoCAD commands, and to combine two
or more commands (or a command and its options) into a single
command.
The COMMAND function calls AutoCAD commands directly from
AutoLISP. COMMAND takes a string argument that must be the name
of an AutoCAD command, and any optional arguments that should be
passed to the command prompts.
For example, this form calls the Line command and draws a line
from 1,1 to 5,5. The form returns nil, because the COMMAND
function always returns nil. Generally, the side-effect of a
COMMAND form is much more interesting than its value.
Command: (command "LINE" "1,1" "5,5" "")
nil
The null string argument at the end of the argument list is
treated as a carriage return by the Line command (or by any
command).
In addition to string arguments for options to commands, COMMAND
will accept reals or integers in the appropriate places, along
with lists of two or three reals as points. COMMAND also accepts
variables with appropriate values.
This is another way to draw a line from 1,1 to 5,5.
(command "LINE" (quote (1.0 1.0)) (quote (5.0 5.0)) "")
In this example, three forms are used to draw a circle with a
center point chosen by the user and a radius of 1.5 units. The
first two forms are used to gather and store data, and the last
to call the Circle command and use the previously-stored
variables as arguments to the COMMAND function.
Command: (setq pt1 (getpoint "\nCenter: "))
Center: <pick>
Command: (setq rad (getdist pt1 "\nRadius: "))
Radius: <pick>
Command: (command "CIRCLE" pt1 rad)
nil
DEFINING NEW COMMANDS
A simple and useful function might be one that combines the Zoom
command with its Window option.
In this example, the special AutoLISP symbol pause is used as an
argument to the COMMAND function. pause halts the evaluation of
the expression and allows the user to respond to the current
command prompt.
Type this code into a new text file named ZW.LSP, then load the
file into the drawing editor.
(defun ZW ()
(command "ZOOM" "Window" pause pause)
)
Command: (load "ZW")
ZW
Command: (zw)
First corner: <pick>
Other corner: <pick>
nil
The usefulness of this function is somewhat diminished by the
requirement to call it as a form, that is, to enclose the
function name with parentheses and call it as an AutoLISP
function. This requirement means extra typing for the end user,
and the need to remember which commands are enclosed by
parentheses and which aren't.
AutoLISP allows the created of user-defined functions that can be
called from the command prompt without passing them as forms,
that is, without enclosing the function name in parentheses.
Preface the name of the function with C:, as illustrated below.
Add this code to a new text file named ZW.LSP. Load the file.
(defun C:ZW ()
(command "ZOOM" "Window" pause pause)
)
Command: (load "zw")
C:ZW
Command: ZW
or
Command: (C:ZW)
This is an example of a new AutoCAD command named CD. CD draws
circles by center point and diameter.
Add this code to a new text file named CD.LSP. Load the file.
(defun C:CD ()
(command "CIRCLE" pause "Diameter" pause)
)
Command: (load "cd")
C:CD
Command: CD
or
Command: (C:CD)
SUPPRESSING THE VALUE RETURNED BY A USER-DEFINED COMMAND
The value of the last expression in the body of expressions
following the list of required arguments and local variables in a
function definition is always returned as the value of the
function. In many cases, it's nice to stop AutoLISP from
printing this value on the display after the function has been
executed.
The AutoLISP subr PRIN1 will print a null string to the display
if PRIN1 is the last expression in a function definition.
For example, this modified version of the command CD does not
print "nil" at the command prompt after it has executed.
(defun C:CD ()
(command "CIRCLE" pause "Diameter" pause)
(prin1)
)
REQUIRED ARGUMENTS TO A FUNCTION
Some functions take no arguments; some require one or more, or a
variable number of arguments. The SETQ function, for example,
requires at least two arguments.
Arguments may be required during a function call if they have
been included in the function definition. The values of the
arguments will be mapped into the expressions following the list
of required arguments wherever variables of the same names as
those defined in the list of required arguments have been used.
Consider this function definition, which requires no arguments.
It prompts the user for a real number, treats the number as a
value in decimal degrees, and returns the value of the number
converted into radians.
(defun dtr ()
(setq degree (getreal "\nDegrees: "))
(/ (* degree pi) 180.0)
)
This function must be called with only one object in the form;
the function itself.
Command: (dtr)
Degrees: 180
3.14159
An equivalent expression may be created which requires the value
in degrees as an argument in the form that contains the function.
(defun dtr (degree)
(/ (* degree pi) 180.0)
)
In this case, the function must be called with an argument.
Command: (dtr 180)
3.14159
The value of the argument 180 in the previous form becomes the
value of the required argument DEGREE and AutoLISP subsequently
uses the value 180 anywhere in the expressions following the list
of required arguments where the variable DEGREE has been used.
Next week: Writing New AutoCAD Commands, Part Two
Questions:
1. What are subrs?
2. What is a form?
3. What is the difference between a form and a list (or complex
expression) that must be treated strictly as data?
4. What kind of atom must always be the first element in any
form?
5. What subr allows the user to create his own functions?
6. What are the two required arguments to the function in
Question 5?
7. What are the optional arguments to the function in Question
5?
8. What value is returned by a user-defined function?
9. How can you use an external file that contains AutoLISP code
in the drawing editor?
10. What special symbol allows the user to respond to prompts
generated by AutoCAD commands called by the AutoLISP COMMAND
function?
11. How can you eliminate the need for a user to call a function
by enclosing it in parentheses?
12. What function will print a null string if included as the
last expression in a function definition?
13. How can a user define a function so that it requires an
argument?
14. Where are the values of required arguments used within the
expressions that comprise the processing instructions of a
user-defined function?